package org.linlinjava.litemall.wx.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.linlinjava.litemall.core.pojo.PageParam;
import org.linlinjava.litemall.core.util.AdminCouponDateUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.domain.LumiereCoupon;
import org.linlinjava.litemall.db.domain.LumiereCouponStrategy;
import org.linlinjava.litemall.db.domain.LumiereCouponUser;
import org.linlinjava.litemall.db.dto.WxCountUserCouponsDTO;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.util.WxResponseCode;
import org.linlinjava.litemall.wx.vo.WxHomeIndexVO;
import org.linlinjava.litemall.wx.vo.WxMyCouponsVO;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class WxLumiereCouponStrategyService {

    private final LumiereCouponUserService lumiereCouponUserService;

    private final LumiereCouponService lumiereCouponService;

    private final LumiereCouponStrategyService lumiereCouponStrategyService;

    private final LitemallUserService litemallUserService;

    private final LitemallCategoryService litemallCategoryService;

    private final LitemallGoodsService litemallGoodsService;

    private final LitemallRegionService litemallRegionService;


    public ResponseUtil.Response coupons( Integer userId,Integer page, Integer limit, Integer type) {
        //PageHelper.startPage(page , limit);
        limit = PageParam.PAGE_SIZE_NONE;
        IPage<WxMyCouponsVO> wxMyCouponsVOS = lumiereCouponUserService.selectJoinListPage(new Page<>(page,limit),WxMyCouponsVO.class, new MPJLambdaWrapper<LumiereCouponUser>()
                .selectAs(LumiereCouponStrategy::getName, WxMyCouponsVO::getCouponName)
                .selectAs(LumiereCouponStrategy::getRanges, WxMyCouponsVO::getRanges)
                .selectAs(LumiereCoupon::getId,WxMyCouponsVO::getCouponId)
                .select(LumiereCoupon::getDescr,LumiereCoupon::getPictureUrl)
                .select(LumiereCouponUser::getStartTime, LumiereCouponUser::getEndTime, LumiereCouponUser::getCode, LumiereCouponUser::getAddTime)
                .select(LumiereCouponStrategy::getDiscountType,
                        LumiereCouponStrategy::getDiscountRate,
                        LumiereCouponStrategy::getDiscount,
                        LumiereCouponStrategy::getMin,
                        LumiereCouponStrategy::getUseLimit,
                        LumiereCouponStrategy::getUseLimitNum,
                        LumiereCouponStrategy::getUseInstruction,
                        LumiereCouponStrategy::getCouponType,
                        LumiereCouponStrategy::getGoodsType,
                        LumiereCouponStrategy::getGoodsValue,
                        LumiereCouponStrategy::getSelectGoods,
                        LumiereCouponStrategy::getAreaLimit,
                        LumiereCouponStrategy::getRegions)
                .isNull(type==0,LumiereCouponUser::getUsedTime)
                .gt(type==0,LumiereCouponUser::getEndTime,LocalDateTime.now())
                .lt(type==2,LumiereCouponUser::getEndTime,LocalDateTime.now())
                .eq(LumiereCouponUser::getUserId,userId)
                .eq(LumiereCouponUser::getDeleted,0)
                .isNotNull(type==1,LumiereCouponUser::getUsedTime)
                .leftJoin(LumiereCoupon.class, LumiereCoupon::getId, LumiereCouponUser::getCouponId)
                .leftJoin(LumiereCouponStrategy.class, LumiereCouponStrategy::getId, LumiereCouponUser::getStrategyId)
                .orderByDesc(LumiereCouponUser::getAddTime)
        );
        wxMyCouponsVOS.getRecords().stream().forEach(wxMyCouponsVO -> {
            //拿到限制名
            if(wxMyCouponsVO.getGoodsValue().length>0){
                wxMyCouponsVO.setGoodsValue(litemallCategoryService.getByIds(wxMyCouponsVO.getGoodsValue()));
            }
            if(wxMyCouponsVO.getSelectGoods().length>0){
                wxMyCouponsVO.setSelectGoods(litemallGoodsService.getByIds(wxMyCouponsVO.getSelectGoods()));
            }
            if(wxMyCouponsVO.getRegions().length>0){
                wxMyCouponsVO.setRegions(litemallRegionService.getByIds(wxMyCouponsVO.getRegions()));
            }
        });

        // 根据couponName字段进行分组和统计数量，并保留完整对象
        Map<String, WxMyCouponsVO> couponNameMap = wxMyCouponsVOS.getRecords().stream()
                .collect(Collectors.groupingBy(coupon -> String.valueOf(coupon.getCouponId()), Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> {
                            WxMyCouponsVO vo = list.stream()
                                    //根据结束时间排序
                                    .sorted((coupon1, coupon2) -> coupon1.getEndTime().compareTo(coupon2.getEndTime()))
                                    .collect(Collectors.toList()).get(0);
                            vo.setNumber(list.size());
                            return vo;
                        }
                )));

        // 输出每个couponName及其对应的WxMyCouponsVO对象（包含数量）
        List<WxMyCouponsVO> wxMyCouponsVOList = CollUtil.newArrayList();
        for (Map.Entry<String, WxMyCouponsVO> entry : couponNameMap.entrySet()) {
            wxMyCouponsVOList.add(entry.getValue());
        }
        return ResponseUtil.okList(wxMyCouponsVOList);
    }

    public List homeCouponList(Integer userId) {
        //查询全部
        List<WxHomeIndexVO> wxHomeIndexVOS = lumiereCouponStrategyService.selectJoinList(WxHomeIndexVO.class, new MPJLambdaWrapper<LumiereCouponStrategy>()
                .selectAs(LumiereCouponStrategy::getId, WxHomeIndexVO::getStyategyId)
                .selectAs(LumiereCoupon::getId, WxHomeIndexVO::getCouponId)
                .select(LumiereCoupon::getPictureUrl)
                .selectAs(LumiereCouponStrategy::getName, WxHomeIndexVO::getCouponName)
                .select(LumiereCouponStrategy::getDiscountType, LumiereCouponStrategy::getDiscountRate, LumiereCouponStrategy::getDiscount, LumiereCouponStrategy::getMin, LumiereCouponStrategy::getUserLimit, LumiereCouponStrategy::getUseInstruction, LumiereCouponStrategy::getIsShow, LumiereCouponStrategy::getTimeType, LumiereCouponStrategy::getDays, LumiereCouponStrategy::getStartTime, LumiereCouponStrategy::getEndTime)
                .eq(LumiereCouponStrategy::getStatus, 1)
                .eq(LumiereCouponStrategy::getCouponType, 1)
                .eq(LumiereCouponStrategy::getIsShow, 1)
                .eq(LumiereCouponStrategy::getDeleted, 0)
                .leftJoin(LumiereCoupon.class, LumiereCoupon::getId, LumiereCouponStrategy::getCouponId));
        if (userId != null) {
            //已经登陆
            //计算当前用户已经领取的数量 
            wxHomeIndexVOS.stream().forEach(wxHomeIndexVO -> {
                long pullNum = lumiereCouponUserService.count(Wrappers.lambdaQuery(LumiereCouponUser.class)
                        .eq(LumiereCouponUser::getCouponId, wxHomeIndexVO.getCouponId())
                        .eq(LumiereCouponUser::getStrategyId, wxHomeIndexVO.getStyategyId())
                        .eq(LumiereCouponUser::getUserId, userId));
                wxHomeIndexVO.setPullNum(pullNum);
            });
            //将已经领取上限的优惠券策略去掉
            wxHomeIndexVOS = wxHomeIndexVOS.stream().filter(wxHomeIndexVO -> {
                boolean b = wxHomeIndexVO.getUserLimit() <= wxHomeIndexVO.getPullNum();
                return !b;
            }).collect(Collectors.toList());
        }
        wxHomeIndexVOS= wxHomeIndexVOS.stream().filter(wxHomeIndexVO ->{
                    if(wxHomeIndexVO.getTimeType()==0){
                        return true;
                    }
                    return wxHomeIndexVO.getStartTime().isBefore(LocalDateTime.now())&&wxHomeIndexVO.getEndTime().isAfter(LocalDateTime.now());
                })
                .collect(Collectors.toList());
        return wxHomeIndexVOS;
    }

    public ResponseUtil.Response pullCoupon(Integer userId, Long strategyId) {
        if (userId == null) {return ResponseUtil.unlogin();}
        LitemallUser litemallUser = litemallUserService.findById(userId);
        if (strategyId == null) {return ResponseUtil.badArgument();}
        LumiereCouponStrategy lumiereCouponStrategy = lumiereCouponStrategyService.getById(strategyId);
        if (lumiereCouponStrategy == null) {return ResponseUtil.badArgumentValue();}
        if(lumiereCouponStrategy.getStatus()==false){
            return ResponseUtil.fail(WxResponseCode.COUPON_STATUS_SOLD_OUT,"优惠券已下架");
        }
        //账户已领取的优惠券是否超过单人可领取的数量
        long pullNum = lumiereCouponUserService.count(Wrappers.lambdaQuery(LumiereCouponUser.class)
                .eq(LumiereCouponUser::getStrategyId, lumiereCouponStrategy.getId())
                .eq(LumiereCouponUser::getCouponId, lumiereCouponStrategy.getCouponId())
                .eq(LumiereCouponUser::getUserId, userId));
        if (lumiereCouponStrategy.getUserLimit()!=0&&pullNum == lumiereCouponStrategy.getUserLimit()) {
            return ResponseUtil.fail(WxResponseCode.COUPON_EXCEED_OVER_LIMIT, "领取优惠券上限，领取失败");
        }
        // 当前已领取数量和总数量比较
        long totalCoupons = lumiereCouponUserService.count(Wrappers.lambdaQuery(LumiereCouponUser.class)
                .eq(LumiereCouponUser::getStrategyId, lumiereCouponStrategy.getId())
                .eq(LumiereCouponUser::getCouponId, lumiereCouponStrategy.getCouponId()));
        if ((lumiereCouponStrategy.getTotal() != 0) && (totalCoupons >= lumiereCouponStrategy.getTotal())) {
            return ResponseUtil.fail(WxResponseCode.COUPON_EXCEED_LIMIT, "优惠券已领完");
        }
        //领取成功
        long nextId = IdUtil.getSnowflake(2, 2).nextId();
        LocalDateTime[] localDateTimes = AdminCouponDateUtil.calculateExpirationTime(lumiereCouponStrategy);
        LumiereCouponUser couponUser = LumiereCouponUser.builder()
                .userId(userId)
                .strategyId(strategyId)
                .couponId(lumiereCouponStrategy.getCouponId())
                .startTime(localDateTimes[0])
                .endTime(localDateTimes[1])
                .userName(litemallUser.getUsername())
                .code(String.valueOf(nextId))
                .addTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .deleted(false)
                .build();
        boolean save = lumiereCouponUserService.save(couponUser);
        return save?ResponseUtil.ok("领取成功"):ResponseUtil.fail("领取失败！");
    }
}
